﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.IO.Ports;
using System.Diagnostics;
using System.Collections;
using System.Reflection;
using System.Management;
using System.Text.RegularExpressions;
using Collector.Device;

namespace Collector
{
    public partial class FormMain : Form
    {
        #region 静态成员和函数
        //public static ComPortPack comPort = ComPortPack.GetComPortPack();
        public ComPortPack instanceSerPort = null;
        #endregion

        private string mInputPCBSN = null;
        private string mFixedFrequency = "";
        private bool isFactoryTestMode = false;

        private string UserPhoneNum = "137xxxxxxxx";
        private bool UserLeftHandSel = false; // no use
        private bool UserRightHandSel = false;

        long TimeCount = 0;
        //定义委托
        public delegate void SetControlValue(long value);
        // 配置定时器
        System.Timers.Timer tSensor = new System.Timers.Timer(100);
        System.Timers.Timer tTestTimer = new System.Timers.Timer(1000);

        //FileStream WaveFileStream;
        Setting settingFrom;
        ScanSn InputSn = null;// new ScanSn();
        ScanNum InputPhoneNum;

        // 日志文件
        //string logfile = "logs/" + DateTime.Now.ToString("yyyy-MM-dd") + "_log.csv";
        string LogFile_RecordmmHg = "";
        // 记录200个点用于计算平均压力值
        Queue<double> airPressure_data = new Queue<double>();
        Queue<double> wave_data = new Queue<double>();

        const int QUEUE_AIRPRESSURE_LENGTH = 10;
        const int THREE_BODY_PART_SNR_MAXIMUM = 3;
        double[] baseline_value = new double[THREE_BODY_PART_SNR_MAXIMUM];

        // Refactoring defined @ Sven
        private DeviceCommunicationManager mDCManager = new DeviceCommunicationManager();
        private PulseGeneralCollector mGeneralCollector = new PulseGeneralCollector();
        private PulseApplicantion mApplication = new PulseApplicantion();
        // end

        List<string> airPressureDataLogList_ = new List<string>();
        public List<string> airPressureDataLogList
        {
            get { return airPressureDataLogList_; }
            set { airPressureDataLogList_ = value; }
        }
        List<string> pulseDataLogList_ = new List<string>();
        public List<string> pulseDataLogList
        {
            get { return pulseDataLogList_; }
            set { pulseDataLogList_ = value; }
        }
        List<string> pulseBasicDataCsvSaveList_ = new List<string>();
        public List<string> PulseBasicDataCsvSaveList
        {
            get { return pulseBasicDataCsvSaveList_; }
            set { pulseBasicDataCsvSaveList_ = value; }
        }

        public int ACKData = -100;
        double ACKDataTotalCount = 0;
        double ACKDataLostCount = 0;
        public SubItemView[] subItemView = new SubItemView[FileConfig.Max_Dut_Count];
        // no use should to remove
        static AutoResetEvent WaitTestEndEvent = new AutoResetEvent(false);
        RunStatus testResult = RunStatus.FAIL;
        

        #region 线程中显示父容器控件委托声明
        // 显示进度条的委托声明
        delegate void ShowProgressDelegate(int totalStep, int currentStep);
        //System.Threading.Thread progress_thread;

        // 进度条父容器显示委托声明
        private delegate void ShowProgressPanelDelegate(bool is_show);
        // 定时器中显示分析结果委托声明
        delegate void ShowPulseResDelegate(PulseRstString pulseResStr, WaveAnalyseRlt m_WaveRst);
        #endregion
        public enum RunStatus
        {
            IDLE = 0,
            PASS,
            FAIL,
            Removed,
            RUNING,
            ERROR,
            END
        }

        public FormMain()
        {
            Log.Debug("FrmMain Entry");
            InitializeComponent();
            this.Width = Screen.PrimaryScreen.Bounds.Width - 60;
            this.Height = Screen.PrimaryScreen.Bounds.Height - 60;
            this.splitContainer1.SplitterDistance = Screen.PrimaryScreen.Bounds.Width - 400;
            this.splitContainer3.SplitterDistance = Screen.PrimaryScreen.Bounds.Width - 640;
                        
            this.toolStripButtonStopScope.Enabled = false;
            this.pictureBox1.Visible = false;
            this.scopeDY.Visible = true;
            this.Shown += new System.EventHandler(this.FrmMain_Shown);

            // 注册配置选项改变的通知事件
            AppEvent.RegistEvent(EventId.UpdateInfo, OnUpdateUI);
            //AppEvent.RegistEvent(EventId.UpdateThresholdValue, UpdateThresholdValues);
            AppEvent.RegistEvent(EventId.TestStop, OnTestStop);
            settingFrom = new Setting();
            LogKeys.Init();
            Log.Debug("FrmMain Leaved");
        }

        private void FrmMain_Shown(object sender, EventArgs e)
        {
            Log.Debug("FrmMain_Shown Entry");
            string file_path = Application.StartupPath + "\\PulseData\\Segment";
            if (!Directory.Exists(file_path))
            {
                Directory.CreateDirectory(file_path);
            }

            for (int i = 0; i < 1; i++)
            {
                subItemView[i] = new SubItemView(i);
                subItemView[i].SubItemIndex = i;                
                subItemView[i].Dock = DockStyle.Fill;                
                subItemView[i].Visible = true;
                panel3.Controls.Add(subItemView[i]);

            }

            this.Text = Application.ProductName + " - " + Application.ProductVersion;
            //this.label_TestMode.Text = FileConfig.testMode_Info[FileConfig.CommonParam.iSelectedTestmode].mode;

            Log.Debug("FrmMain_Shown Leaved");
        }

        private void OnUpdateUI(object sender, AppEventArgs e)
        {
            if (e.State == EventState.UI)
            {
                //var info = e.Reserved;
                if (Convert.ToInt32(e.Reserved) == 0)
                    isFactoryTestMode = true;
                else
                    isFactoryTestMode = false;
                //更新测试模式状态
                string TestModeInfo = e.Data as string;
                this.label_TestMode.Text = TestModeInfo;

                if(FileConfig.PulseThreeBodyTest())
                {                    
                    this.textBox_curveValue1.Visible = true;
                    this.textBox_curveValue2.Visible = true;
                    this.label_realtimePulsePressure1.Visible = true;
                    this.label_realtimePulsePressure2.Visible = true;
                    this.textBox_baseline1.Visible = true;
                    this.label1_baseline1.Visible = true;
                    this.textBox_baseline2.Visible = true;
                    this.label1_baseline2.Visible = true;
                    this.textBox_pressed1.Visible = true;
                    this.label2_pulse_diff1.Visible = true;
                    this.textBox_pressed2.Visible = true;
                    this.label2_pulse_diff2.Visible = true;
                }
                else
                {
                    this.textBox_curveValue1.Visible = false;
                    this.textBox_curveValue2.Visible = false;
                    this.label_realtimePulsePressure1.Visible = false;
                    this.label_realtimePulsePressure2.Visible = false;
                    this.textBox_baseline1.Visible = false;
                    this.label1_baseline1.Visible = false;
                    this.textBox_baseline2.Visible = false;
                    this.label1_baseline2.Visible = false;
                    this.textBox_pressed1.Visible = false;
                    this.label2_pulse_diff1.Visible = false;
                    this.textBox_pressed2.Visible = false;
                    this.label2_pulse_diff2.Visible = false;
                }
            }
        }

        private void OnTestStop(object sender, AppEventArgs e)
        {
            if (e.State != EventState.TestStop)
            {
                return;
            }

            this.Invoke(new MethodInvoker(delegate
            {
                // 模拟点击Stop Button按钮
                this.toolStripButtonStopScope.PerformClick();
            }));
        }

        /// <summary>
        /// 设置按钮，点击后弹出设置选择框，通过勾选复选框进行配置测试项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonConfig_Click(object sender, EventArgs e)
        {
            settingFrom.ShowDialog();
        }

        /// <summary>
        /// 开始测试按钮，点击后开始脉象功能测试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>        
        private void toolStripButtonRunScope_Click(object sender, EventArgs e)
        {
            Log.Debug("toolStripButtonRunScope_Click() Entry");
            this.Invoke((EventHandler)delegate
            {
                this.toolStripButtonRunScope.Enabled = false;
                this.toolStripButtonStopScope.Enabled = true;
                this.btn_RefeshBaseLine.Enabled = true;
                //this.btn_ManualPress.Enabled = true;
                this.btn_ManualTest.Enabled = true;
                this.btn_StopReset.Enabled = true;
                //this.btn_RunInTest.Enabled = false;
                this.scopeDY.Visible = true;
                this.pictureBox1.Visible = false;
                //清除listView数据
                AppEvent.CallEvent(this, new AppEventArgs(EventId.TestStart, 0, EventState.Invalid, null, null));
                // 清空右侧显示测试结果的文本框
                this.rtbMsg.Clear();
            });

            //区分工厂测试模式、用户测试模式
            if (isFactoryTestMode)
            {
                if (FileConfig.PulseSFTTest() && !FileConfig.PulseFFTTest())
                {
                    this.ShowMsg("单板功能测试", LogMsgType.INFO);
                    this.label_TestMode.Text = "单板功能测试";
                }
                else if (!FileConfig.PulseSFTTest() && FileConfig.PulseFFTTest())
                {
                    this.ShowMsg("整机功能测试", LogMsgType.INFO);
                    this.label_TestMode.Text = "整机功能测试";
                }
                else if(FileConfig.WriteFixedFrequency())
                {
                    this.ShowMsg("写气泵固定频率", LogMsgType.INFO);
                    this.label_TestMode.Text = "气泵固定频率";
                }
                else
                {
                    this.ShowMsg(string.Format("配置功能测试项错误"), LogMsgType.ERROR);
                    return;
                }

                if (FileConfig.WritePCBSN() || FileConfig.WriteFixedFrequency())
                {
                    //add by guozw
                    InputSn = new ScanSn();
                    InputSn.SerialNumberInputed += new SerialNumberInputedEventHandler(scanSerialNumber_SerialNumberInputed);
                    InputSn.Show();
                    InputSn.Focus();
                }
                else
                {
                    RunSingleTest();
                }
            }
            else
            {
                //add by guozw
                InputPhoneNum = new ScanNum();
                InputPhoneNum.PhoneNumberInputed += new PhoneNumberInputedEventHandler(scanPhoneNumberInputed);
                InputPhoneNum.Show();
                InputPhoneNum.Focus();
            }

            Log.Debug("toolStripButtonRunScope_Click() Leaved");
        }

        private void toolStripButtonStopScope_Click(object sender, EventArgs e)
        {
            this.ShowMsg("StopScope_Click", LogMsgType.INFO);
            RunFuncWithShowItem(true, "测试时长", labTotalTime.Text.ToString());

            if (FileConfig.WritePCBSN() && isFactoryTestMode)
            {
                if (InputSn != null)
                {
                    InputSn.Close();
                    InputSn.Dispose();
                }
            }

            this.Invoke((EventHandler)delegate
            {
                this.toolStripButtonRunScope.Enabled = true;
                this.toolStripButtonStopScope.Enabled = false;
                this.btn_RefeshBaseLine.Enabled = false;
                this.btn_ManualPress.Enabled = false;
                this.btn_ManualTest.Enabled = false;
                //this.btn_RunInTest.Enabled = true;
            });

            ResetDeviceStatus();
            ReleaseSerialPort();
        }

        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            MatlabSaveToBitmap();
            MessageBox.Show("波形保存成功");
            return;           
        }

        private void MatlabSaveToBitmap()
        {
            string file_name = DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".bmp";
            string toBitMapFile = Application.StartupPath + "\\PulseData\\" + file_name;
            scopeDY.SaveToBitmap(toBitMapFile);
        }

        void scanSerialNumber_SerialNumberInputed(object sender, SerialNumberInputedEventArgs e)
        {
            // 获得写入的固定频率
            mFixedFrequency = e.ModuleIndex;//固定频率
            //this.ShowMsg("Get from barcode scanner :" + mInputPCBSN, LogMsgType.INFO);
            // 获得写入的SN号
            mInputPCBSN = e.SerialNumber;
            RunSingleTest();
        }

        void scanPhoneNumberInputed(object sender, PhoneNumberInputedEventArgs e)
        {
            UserPhoneNum = e.PhoneNumber;
            UserLeftHandSel = e.LeftHand;
            UserRightHandSel = e.RightHand;

            RunSingleTest();
            InputPhoneNum.Close();
            InputPhoneNum.Dispose();
        }

        public void RunSingleTest()
        {
            Thread mainTestThread_ = new Thread(testThread);
            mainTestThread_.Start();
        }

        private bool CheckDeviceVersion()
        {
            string MCUConfigVersion, MCUTargetVersion;
            bool finalResult;

            // 从配置文件中读取设备的测试目标版本号
            FileConfig.getmmHgListInfo("CheckMcuVersion", out MCUConfigVersion);
            // 从设备读取固件版本号
            finalResult = mDCManager.ReadMcuVersion(out MCUTargetVersion);
            if(finalResult)
            {
                finalResult = MCUConfigVersion.Trim() == MCUTargetVersion.Trim();
            }
            
            // Update UI
            RunFuncWithShowItem(finalResult, "Read MCUVersion", MCUTargetVersion + ", Read MCU Version Result");
            this.ShowMsg(string.Format("Read:{0},config:{1}", MCUTargetVersion, MCUConfigVersion),
                    finalResult ? LogMsgType.INFO : LogMsgType.ERROR);

            // 记录版本号
            PulseBasicDataCsvSaveList.Add(MCUTargetVersion);

            return finalResult;
        }

        private bool BurnDeviceSerialNumber()
        {
            string pcbSN = "";
            if (!FileConfig.PulseFFTTest() || !isFactoryTestMode)
            {
                return false;                
            }
            
            this.ShowMsg("Get from barcode scanner :" + mInputPCBSN, LogMsgType.INFO);
            if(!WriteSerialNumber(mInputPCBSN))
            {
                RunFuncWithShowItem(false, "Write new pcbSN", mInputPCBSN + ", Write Fail");
                return false;
            }
            // 写入后，读出进行校验
            mDCManager.ReadSerialNumber(out pcbSN);
            this.ShowMsg("Read SN:" + pcbSN, LogMsgType.INFO);
            if (pcbSN != mInputPCBSN)
            {
                RunFuncWithShowItem(false, "Write new pcbSN", pcbSN + ", Write Fail");
                return false;
            }
            
            this.ShowMsg("Write SN PASS", LogMsgType.INFO);
            RunFuncWithShowItem(true, "Write pcbSN", pcbSN + ", Write Success");

            PulseBasicDataCsvSaveList.Add(pcbSN);
            return true;
        }

        private bool BurnDevicePumpDriverFrequency()
        {
            string fixedFrequency_;
            
            if (!isFactoryTestMode)
            {
                return false;
            }

            this.ShowMsg("Get from mFixedFrequency scanner :" + mFixedFrequency, LogMsgType.INFO);
            if(String.IsNullOrEmpty(mFixedFrequency))
            {
                return false;
            }
            //写固定频率
            if (!mDCManager.WriteDeviceFixedFre(mFixedFrequency))
            {
                RunFuncWithShowItem(false, "Write fixedFrequency", mFixedFrequency + ", Write Fail");
                Log.Debug("Write fixedFrequency Fail " + mFixedFrequency);
                return false;
            }

            if (!mDCManager.ReadDeviceFixedFre(out fixedFrequency_))
            {
                Log.Debug("Read fixedFrequency Fail");
                return false;
            }

            this.ShowMsg("Read fixedFrequency:" + fixedFrequency_, LogMsgType.INFO);
            if (fixedFrequency_ != mFixedFrequency)
            {
                RunFuncWithShowItem(false, "Write fixedFrequency", fixedFrequency_ + ", Write Fail");
                Log.Debug("Write fixedFrequency Fail, new freq: " + mFixedFrequency + " read freq: " + fixedFrequency_);
                return false;
            }

            this.ShowMsg("Write fixedFrequency PASS", LogMsgType.INFO);
            RunFuncWithShowItem(true, "Write fixedFrequency", fixedFrequency_ + ", Write Success");

            return true;
        }

        public bool DeviceAirCalibration()
        {
            bool ret;
            double pressureOfPeeling;

            if (!mDCManager.AirpressureCalibration())
            {
                this.ShowMsg(string.Format("{0},ResetInitAir ACK Answer Back Error.", instanceSerPort.serialPort.PortName), LogMsgType.ERROR);
                return false;
            }

            // read pressureOfPeeling
            ret = mDCManager.ReadAirPressureOfPeeling(out pressureOfPeeling);
            if (ret)
            {
                //下98指令,读取设备气压值3000Pa
                this.ShowMsg(string.Format("气压零飘值 :{0}Pa", pressureOfPeeling), LogMsgType.INFO);
                if (pressureOfPeeling >= FileConfig.GetThresholdValue("InitAirPressureValue"))
                {
                    Log.Debug("air pressure Calibration is not match, {0}Pa -> {1}Pa 气压传感器异常 ", 
                        pressureOfPeeling, FileConfig.GetThresholdValue("InitAirPressureValue"));

                    throw new Exception(string.Format("{0}Pa -> {1}Pa 气压传感器异常", 
                        pressureOfPeeling, FileConfig.GetThresholdValue("InitAirPressureValue")));
                }
            }
            else
            {
                Log.Debug("Read air pressure of the peel is failed");
            }

            return ret;
        }

        private bool CheckLedTest()
        {
            bool ret;
            if(!FileConfig.LedTest())
            {
                return false;
            }

            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler(delegate
                {
                    LedFrm ledFrm = new LedFrm(instanceSerPort, TestItemFlow.Led1Test);
                    ledFrm.ShowDialog();
                    ret = ledFrm.TestState;
                    RunFuncWithShowItem(ret, "LED 灯测试", "LED 灯测试结果");
                    if (ret)
                    {
                        this.ShowMsg("LED TEST PASS", LogMsgType.INFO);
                    }
                    else
                    {
                        throw new Exception("LED TEST FAIL");
                    }
                }));
            }
            else
            {
                LedFrm ledFrm = new LedFrm(instanceSerPort, TestItemFlow.Led1Test);
                ledFrm.ShowDialog();
                ret = ledFrm.TestState;
                RunFuncWithShowItem(ret, "LED 灯测试", "LED 灯测试结果");
                if (ret)
                {
                    this.ShowMsg("LED TEST PASS", LogMsgType.INFO);
                }
                else
                {
                    throw new Exception("LED TEST FAIL");
                }
            }

            return true;
        }

        private bool FullFunctionTest()
        {
            bool ret = false;
            if (!FileConfig.PulsePressureTest() || !FileConfig.AirPressureTest())
            {
                Log.Error("Please select pulse and air pressure test");
                return false;
            }

            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler(delegate
                {
                    ProFrm Frm_ = new ProFrm(string.Format("请正确佩戴设备,状态指示灯正常!."));
                    Frm_.ShowDialog(this);
                    if (!Frm_.TestState)
                        throw new Exception(string.Format("未正确佩戴设备，测试结束"));
                }));
            }
            else
            {
                ProFrm Frm_ = new ProFrm(string.Format("请正确佩戴设备,状态指示灯正常."));
                Frm_.ShowDialog(this);
                if (!Frm_.TestState)
                    throw new Exception(string.Format("未正确佩戴设备，测试结束"));
            }

            //分段加压
            if (FileConfig.PulseSubsectionTest())
            {
                ret = DoSubsection_TestmmHg();
            }
            //连续加压
            else if (FileConfig.PulseConsecutiveTest())
            {
                ret = DataConsecutive_TestmmHg();
            } 
            // 三部分段加压
            else if(FileConfig.PulseThreeBodyTest_Subsection())
            {
                ret = DoThreeBodyTest_Subsection();
            // 三部连续加压
            } else if(FileConfig.PulseThreeBodyTest_Continuous())
            {
                ret = DoThreeBodyTest_Continuous();
            }

            if (ACKDataLostCount > 0)
            {
                double maxLostRate = Convert.ToDouble(1) / Convert.ToDouble(2000);
                bool bACKDataLossRate = (ACKDataLostCount / ACKDataTotalCount) > maxLostRate;
                if (bACKDataLossRate)
                {
                    this.ShowMsg("ACKData LossRate :" + (ACKDataLostCount.ToString() + "/" + ACKDataTotalCount.ToString()), LogMsgType.ERROR);
                    throw new Exception(string.Format("脉压数据丢包"));
                }
            }

            this.ShowMsg(string.Format("丢包率 :{0}/{1}", ACKDataLostCount.ToString(), ACKDataTotalCount.ToString()), LogMsgType.DEBUG);
            RunFuncWithShowItem(true, "脉压数据丢包", "丢包次数 :" + ACKDataLostCount +
                    ",丢包率 :" + ACKDataLostCount.ToString() + "/" + ACKDataTotalCount.ToString());
            
            return ret;
        }

        private void SetLEDFlicker()
        {
            if (mDCManager != null)
                mDCManager.SPLedFlicker();
        }

        /// <summary>
        /// 遍历查找脉象仪设备并打开Serialport端口
        /// 打开遍历到的第一个脉象设备
        /// </summary>
        /// <returns></returns>
        private bool InitSerialPort()
        {
            bool isComPortOpen = false;
            string portInfo = "";
            string portName = "";
            
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_PnPEntity"))
            {
                var hardInfos = searcher.Get();
                foreach (var hardInfo in hardInfos)
                {
                    portInfo = hardInfo.Properties["DeviceID"].Value.ToString();
                    if (!string.IsNullOrEmpty(portInfo) && portInfo.Contains("VID_28E9&PID_018A"))
                    {
                        //string strComName = hardInfo.Properties["Name"].Value.ToString();
                        portName = Regex.Replace(hardInfo.Properties["Name"].Value.ToString(), @"(.*\()(.*)(\).*)", "$2").Trim();
                        Log.Debug(string.Format("DeviceName:{0},DeviceID:{1}", portName, portInfo));//打印串口设备名称及串口号
                    }
                }
            }

            // 配置串口，按照115200-8-1-无的方式配置
            ComPortPack.SerialPortModel model = new ComPortPack.SerialPortModel();
            model.PortName = portName;
            model.BaudRate = 115200;
            model.Parity = Parity.None;
            model.StopBits = StopBits.One;
            model.DataBits = 8;

            instanceSerPort = new ComPortPack(model);

            // open SerPort
            if (!instanceSerPort.Open())
                return false;

            isComPortOpen = instanceSerPort.IsOpen();
            this.ShowMsg(string.Format("comPort {0} Open Status:{1}", portName, isComPortOpen), LogMsgType.INFO);
            // Default set general collector.
            instanceSerPort.collector = mGeneralCollector;

            if (isComPortOpen)
            {
                // 实时刷新测试时间
                this.msgComPort.Invoke(new EventHandler(delegate
                {
                    this.msgComPort.Text = "测试串口 :" + portName;
                    TimeCount = 0;
                    timerTotalTest(tTestTimer);
                }));
            }

            return isComPortOpen;
        }

        /// <summary>
        /// 释放脉象设备端口
        /// </summary>
        private void ReleaseSerialPort()
        {
            if (null != instanceSerPort)
            {
                Log.Debug("SerialPortReceivedCallback Release");
                instanceSerPort.Received -= mDCManager.SerialPortReceivedCallback;
                RemoveEvent<ComPortPack>(instanceSerPort, "Received");
                if (instanceSerPort.IsOpen())
                {
                    Log.Debug("MainFormComPort close serialport");
                    instanceSerPort.Close();
                    instanceSerPort = null;
                }
            }

            timerSensorDesetting(tSensor);
            timerDeTotalTest(tTestTimer);
        }

        /// <summary>
        /// 脉象初始化准备
        /// </summary>
        /// <returns></returns>
        private bool InitializePulseDevice()
        {
            bool ret = false;

            // 重置 脉象协议处理类配置
            mDCManager.ResetConfig();
            mDCManager.DeviceConnector = instanceSerPort;
            // 用于接收实时脉压和气压值
            mDCManager.DeliveredCallback = DeliveredPulsePressureDataCallback;
            // 设置serialport received callback function
            instanceSerPort.Received += mDCManager.SerialPortReceivedCallback;

            // 打开脉象设备灯，保持长亮
            mDCManager.OpenDeviceLed();

            // 请求复位设备
            ret = mDCManager.ResetDevice();

            //开始定时器，100ms频次显示当前脉压值和脉压差值
            timerSensorSetting(tSensor);

            return ret;
        }

        private void ResetDeviceStatus()
        {
            byte[] payload;
            if (null == instanceSerPort)
            {
                Log.Warn("ResetDeviceStatus:Pulse Serialport is released");
                return;
            }

            if (!mDCManager.SendCommandToDevice("SPStopPulsePressure", 0x74, out payload))
            {
                Log.Error("ResetDeviceStatus:Stop pulse pressure collect failed");
            }

            if (!mDCManager.SendCommandToDevice("SPStopAirPressure", 0x96, out payload))
            {
                Log.Error("ResetDeviceStatus:Stop air pressure collect failed");
            }

            if (!mDCManager.ResetDevice())
            {
                Log.Error("ResetDeviceStatus:Reset device status failed");
            }
            else
            {
                Log.Info("ResetDeviceStatus:Reset device status Successfuly");
            }
        }

        private void testThread()
        {
            bool finalResult = false;
            double read_initAirValue = 0.0;
            string fixedFrequency_ = "";
            string MCU_Version = "";
            string config_mcuVersion = "";

            this.ShowInfo("Running", Color.Yellow);

            //变量重新初始化
            for (int i=0; i< THREE_BODY_PART_SNR_MAXIMUM; i++)
                baseline_value[i] = 0;

            this.wave_data.Clear();
            this.airPressure_data.Clear();
            this.PulseBasicDataCsvSaveList.Clear();
            testResult = RunStatus.PASS;
            
            // 清除数据
            if(FileConfig.CommonParam.UploadLogEnable)
            {
                if (Directory.Exists("logs"))
                {
                    var logdir = AppDomain.CurrentDomain.BaseDirectory + "Logs";
                    //Directory.CreateDirectory("logs");
                    var files = Directory.GetFiles(logdir);
                    foreach (var item in files)
                    {
                        File.Delete(item);
                    }
                }
            }

            // Init Mitov Plotlab scope
            this.Invoke(new EventHandler(delegate
            {
                this.toolStripButtonStopScope.Enabled = false;

                this.scopeDY.Channels[0].Data.Clear();
                this.scopeDY.Channels[1].Data.Clear();
                this.scopeDY.Channels[2].Data.Clear();
                if (this.scopeDY.SizeLimit != 300)
                {
                    this.scopeDY.SizeLimit = 300;
                    this.scopeDY.RefreshInterval = 100;
                    this.scopeDY.RefreshView();
                }
                this.textBox_curveValue.Text = "";
                this.textBox_baseline.Text = "";
                this.textBox_pressed.Text = "";
                this.textBox_airPressure.Text = "";
            }));

            try
            {
                // should to removed
                WaitTestEndEvent.Reset();
                if (!InitSerialPort())
                    throw new Exception(string.Format("串口打开失败"));

                if(!InitializePulseDevice())
                {
                    throw new Exception("Init MCU Info Fail");
                }

                // 检查设备版本号
                if(!CheckDeviceVersion())
                {
                    throw new Exception("Read MCU Version Fail");
                }

                // 写设备SN
                if (FileConfig.WritePCBSN() && !BurnDeviceSerialNumber())
                {
                    throw new Exception("Burn MCU SerialNumber Fail");
                }

                // 写气泵固定频率
                if(FileConfig.WriteFixedFrequency() && !BurnDevicePumpDriverFrequency())
                {
                    throw new Exception("Burn MCU PUMP driver frequency Fail");
                }

                //气压清零动作放在这里，用配置文件区分
                if (FileConfig.AirResetTest() && !DeviceAirCalibration()) 
                {
                    throw new Exception("MCU air pressure calibration Fail");
                }

                // 读取设备SN
                if (String.IsNullOrWhiteSpace(mInputPCBSN))
                {
                    if(!mDCManager.ReadSerialNumber(out mInputPCBSN))
                    {
                        RunFuncWithShowItem(false, "Read pcbSN", mInputPCBSN + ", Read pcbSN Fail");
                        throw new Exception("Read MCU SerialNumber Fail");
                    }
                }

                this.ShowMsg("Get SN :" + mInputPCBSN, LogMsgType.INFO);
                RunFuncWithShowItem(true, "Read pcbSN", mInputPCBSN + ", Read pcbSN Pass");
                // 记录
                PulseBasicDataCsvSaveList.Add(mInputPCBSN);

                // set hand test direction
                if(FileConfig.PulseThreeBodyTest())
                {
                    if(!mDCManager.SetHandDirection(UserRightHandSel))
                    {
                        throw new Exception(string.Format("设置手的方向失败"));
                    }
                }

                // 读取设备基线压力
                if (!mDCManager.ReadInitialPPressure(ref baseline_value))
                {
                    throw new Exception(string.Format("初始静压值不正确:{0} - {1} - {2}", baseline_value[0], baseline_value[1], baseline_value[2]));
                }

                for(int i=0; i<THREE_BODY_PART_SNR_MAXIMUM; i++)
                {
                    this.ShowMsg("Get baseline_value :" + baseline_value[i], LogMsgType.INFO);
                    if (baseline_value[i] > (FileConfig.GetThresholdValue("BaseLine_UPZH") / 32.0) ||
                        baseline_value[i] < (FileConfig.GetThresholdValue("BaseLine_LowZH") / 32.0))
                    {
                        throw new Exception(string.Format("初始静压值不正确:{0}", baseline_value[i]));
                    }

                    if(!FileConfig.PulseThreeBodyTest())
                    {
                        break;
                    }
                }

                this.textBox_baseline.Invoke(new EventHandler(delegate
                {
                    this.textBox_baseline.Text = baseline_value[0].ToString();
                    this.textBox_baseline.BackColor = Color.Green;
                    if (FileConfig.PulseThreeBodyTest())
                    {
                        this.textBox_baseline1.Text = baseline_value[1].ToString();
                        this.textBox_baseline1.BackColor = Color.Green;
                        this.textBox_baseline2.Text = baseline_value[2].ToString();
                        this.textBox_baseline2.BackColor = Color.Green;
                    }
                }));
                PulseBasicDataCsvSaveList.Add(baseline_value[0].ToString());

                // 读取气泵固定频率                
                if (mDCManager.ReadDeviceFixedFre(out fixedFrequency_))
                {
                    double fixedFreqValue = Math.Round((Convert.ToDouble(fixedFrequency_.Substring(0, 4)) / 100), 2);
                    PulseBasicDataCsvSaveList.Add(fixedFreqValue.ToString());
                    PulseBasicDataCsvSaveList.Add(fixedFrequency_);

                    this.ShowMsg(string.Format("Get fixedFrequency :{0}", fixedFrequency_), LogMsgType.INFO);
                }

                CheckLedTest();

                // 开启脉压和气压采集
                byte[] temp;
                if (!mDCManager.SendCommandToDevice("SPStartPulsePressure", 0x64, out temp))
                    throw new Exception("开启脉压收集失败");
                if (!mDCManager.SendCommandToDevice("SPStartAirPressure", 0x95, out temp))
                    throw new Exception("开启气压收集失败");

                // 读取设备初始气囊压力值
                double Init_AirPressure = 0.0;
                double pressurePeeling = 0;
                double Init_AirPressure_ThresholdValue = FileConfig.GetThresholdValue("Init_AirPressure_ThresholdValue");
                if (mDCManager.ReadAirPressureOfPeeling(out pressurePeeling))
                {
                    // Wait for enough time to collect air pressure
                    Thread.Sleep(1000);
                    if (airPressure_data.Count == QUEUE_AIRPRESSURE_LENGTH)
                    {
                        Init_AirPressure = Math.Round(airPressure_data.Average(), 2);
                    }
                }

                PulseBasicDataCsvSaveList.Add(pressurePeeling.ToString());
                PulseBasicDataCsvSaveList.Add(Init_AirPressure.ToString());

                if (Init_AirPressure < 0 || Init_AirPressure > Init_AirPressure_ThresholdValue)
                {
                    throw new Exception(string.Format("气压初始值异常 :{0}Pa -> {1}Pa", Init_AirPressure,
                            Init_AirPressure_ThresholdValue));
                }
                this.ShowMsg(string.Format("气压初始值 :{0}Pa -> {1}Pa", Init_AirPressure,
                            Init_AirPressure_ThresholdValue), LogMsgType.INFO);


                if (FileConfig.PulseSFTTest())
                {

                }

                if(FileConfig.PulseFFTTest())
                {
                    if(!FullFunctionTest())
                        testResult = RunStatus.FAIL;
                }
            }
            catch (Exception ex)
            {
                this.ShowInfo("FAIL", Color.Red);
                this.ShowMsg("CaughtException :" + ex.Message, LogMsgType.ERROR);
                testResult = RunStatus.FAIL;

                // 重置设备状态
                ResetDeviceStatus();
                ReleaseSerialPort();
            }

            if (testResult == RunStatus.PASS)
            {                
                this.ShowInfo("PASS", Color.Green);
                
                // 重置设备状态
                ResetDeviceStatus();

                // 测试通过灯闪烁
                SetLEDFlicker();

                // 释放Serialport
                ReleaseSerialPort();
            }

            this.Invoke((EventHandler)delegate
            {
                this.toolStripButtonStopScope.Enabled = true;
            });

            SaveLog();

            // Write CVS file
            if (isFactoryTestMode && FileConfig.PulseFFTTest())
            {
                while (true)
                {
                    if (PulseBasicDataCsvSaveList.Count == 24)
                        break;
                    PulseBasicDataCsvSaveList.Add("0");
                }

                PulseBasicDataCsvSaveList[PulseBasicDataCsvSaveList.Count - 1] = testResult.ToString();//强制赋值pass or fail
                string pulseBasicDataInfo = "";
                foreach (var item in PulseBasicDataCsvSaveList)
                {
                    pulseBasicDataInfo += item + ",";
                }

                Log.Debug("pulseBasicDataInfo :"+ pulseBasicDataInfo);
                Log.WriteCsv(pulseBasicDataInfo);
            }
        }

        private int DisplayMessageToUI(PulseCommonHelper.Display obj, PulseCommonHelper.Display.DisplayType type)
        {
            if (type == PulseCommonHelper.Display.DisplayType.eDISPLAY_TYPE_MSG)
            {
                DisplayMessageToUI(obj.displayMsgBox.message, obj.displayMsgBox.type);
            }
            else
            {
                RunFuncWithShowItem(obj.displayRltBox.result, obj.displayRltBox.itemName, obj.displayRltBox.itemInfo);
            }
            return 0;
        }

        private int DisplayMessageToUI(string message, LogMsgType type)
        {
            this.ShowMsg(message, type);
            return 0;
        }

        private bool DeliveredPulsePressureDataCallback(byte[] frame, double data, PulseProtocolPackage.PressureType type)
        {
            switch (type)
            {
                case PulseProtocolPackage.PressureType.ePRESSURE_TYPE_PULSE:
                    {
                        BeginInvoke(new Action(() =>
                        {
                            if(FileConfig.PulseThreeBodyTest())
                            {
                                mApplication.pushPulseData(frame, ProductType.ePRODUCT_TYPE_THREE);
                                
                                // Update scope plotlab value
                                var pluseDataMap = mApplication.PluseData;
                                foreach (var item in pluseDataMap)
                                {
                                    double value = 0.0;
                                    if(item.Value.Count > 0)
                                        value = Math.Round(item.Value.Last(), 2);
                                    if (item.Key == BodyPart.eBODY_PART_CUN)
                                    {
                                        scopeDY.Channels[0].Data.AddYPoint(value - baseline_value[0]);
                                    } 
                                    else if(item.Key == BodyPart.eBODY_PART_GUAN)
                                    {
                                        scopeDY.Channels[1].Data.AddYPoint(value - baseline_value[1]);
                                    }
                                    else if(item.Key == BodyPart.eBODY_PART_CHI)
                                    {
                                        scopeDY.Channels[2].Data.AddYPoint(value - baseline_value[2]);
                                    }
                                }
                            } 
                            else
                            {
                                mApplication.pushPulseData(frame, ProductType.ePRODUCT_TYPE_SINGLE);
                                // Update scope plotlab value
                                var pluseDataMap = mApplication.PluseData;
                                if(pluseDataMap.ContainsKey(BodyPart.eBODY_PART_CUN))
                                {
                                    double value = Math.Round(pluseDataMap[BodyPart.eBODY_PART_CUN].Last(), 2);
                                    scopeDY.Channels[0].Data.AddYPoint(value - baseline_value[0]);
                                }
                            }
                            
                            // TODO:
                            if (FileConfig.CommonParam.DebugPulseData > 0)
                                pulseDataLogList.Add(data.ToString());//log打印脉压数据
                        }));
                    }
                    break;
                case PulseProtocolPackage.PressureType.ePRESSURE_TYPE_AIR:
                    {
                        if (airPressure_data.Count >= QUEUE_AIRPRESSURE_LENGTH)
                            airPressure_data.Dequeue();//在队列的头部读取和删除一个元素，注意，这里读取元素的同时也删除了这个元素
                        airPressure_data.Enqueue(data);//在队列的末端添加元素

                        if (FileConfig.CommonParam.DebugPulseData > 0)
                            airPressureDataLogList.Add(data.ToString());//log打印气压数据
                    }
                    break;
            }

            return true;
        }

        private bool DoSubsection_TestmmHg()
        {
            string mmHgInfo;
            double bmmHgThreSValue = FileConfig.GetThresholdValue("mmHgThresholdValue");//加压mmHg门限值
            // 从配置文件中读取分段压力值
            if (!FileConfig.getmmHgListInfo("mmHg_pPressureList", out mmHgInfo))
            {
                this.ShowMsg(string.Format("{0} 脉压集合列表初始化失败", mmHgInfo), LogMsgType.ERROR);
                return false;
            }
            
            // 将分段压力值转换成int
            List<int> mmHgListInfo = mmHgInfo.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToList();
            // 创建分段对象
            PulseSubsection PSProcessing = new PulseSubsection(baseline_value[0], mmHgListInfo);            
            instanceSerPort.collector = PSProcessing;
            PSProcessing.DeviceCommunication = mDCManager;
            PSProcessing.notifyMainForm += new PulseSubsection.PulseContinuousNotifyDelegate<PulseCommonHelper.Display>(DisplayMessageToUI);            
            PSProcessing.ThresholdRadio = bmmHgThreSValue;
            PSProcessing.RawDataPath = null;

            Log.Debug("FileConfig.CommonParam.AllowSavePulseData={0}", FileConfig.CommonParam.AllowSavePulseData);
            // Write pulse data to file.
            if (FileConfig.CommonParam.AllowSavePulseData > 0)
            {
                PSProcessing.UserRightHandSel = UserRightHandSel;
                PSProcessing.PhoneNumber = UserPhoneNum;
                PSProcessing.SerialNumber = mInputPCBSN;
                PSProcessing.RawDataPath = Application.StartupPath + "\\PulseData\\Segment";
            }

            bool ret = PSProcessing.DoSubsectionProcessing();            
            if(ret)
            {
                RunFuncWithShowItem(true, "分段加压测试", "加压测试 PASS");
                this.ShowMsg("分段加压测试 PASS", LogMsgType.DEBUG);
            } else
            {
                throw new Exception("分段加压测试 Fail");
            }

            // 请求复位设备
            ret = PSProcessing.ResetDevice();
            if(!ret)
            {
                throw new Exception("自动泄压 Fail");
            }

            return ret;
        }

        private bool DataConsecutive_TestmmHg()
        {
            PulseContinuous pulseContinuousHandler = new PulseContinuous();
            PulseContinuous.ContinuousResponseCode responseCode;
            bool bResult = false;
            uint loopCounter = 80;
            if (true) {
                string reason;


                pulseContinuousHandler.ResetContinuousConfigure();
                pulseContinuousHandler.SetCollectorWorkMode(isFactoryTestMode);
                
                // set collector to serialport
                instanceSerPort.collector = pulseContinuousHandler;

                Log.Debug("DataConsecutive_TestmmHg1");
                pulseContinuousHandler.notifyMainForm = new PulseContinuous.PulseContinuousNotifyDelegate<PulseCommonHelper.Display>(DisplayMessageToUI);
                pulseContinuousHandler.DeviceCommunication = mDCManager;

                // Write pulse data to file.
                if (FileConfig.CommonParam.AllowSavePulseData > 0)
                {
                    CreateTestLogFile(out LogFile_RecordmmHg);
                    Log.Debug("save filename: " + LogFile_RecordmmHg);
                    pulseContinuousHandler.RawDataFile = LogFile_RecordmmHg;
                }
                
                Log.Debug("DataConsecutive_TestmmHg2");
                pulseContinuousHandler.ProcessContinuous();
                PulseContinuous.ContinuousState state;
                do
                {
                    Thread.Sleep(1000);
                    //loopCounter--;
                     
                    state = pulseContinuousHandler.GetContinuousState();

                } while (loopCounter > 0 && !(state == PulseContinuous.ContinuousState.eCONTINUOUS_STATE_FINISHED));

                responseCode = pulseContinuousHandler.GetContinuousResponseCode(out reason);
                Log.Debug("连续采脉测试完成 code: " + responseCode + " reason: " + reason);

                if(responseCode < PulseContinuous.ContinuousResponseCode.eCODE_RAPID_WITH_TIMEOUT)
                {
                    bResult = true;
                }
                
            }

            if (bResult)
            {
                RunFuncWithShowItem(true, "连续加压测试", "加压测试 PASS");
                this.ShowMsg("连续加压测试 PASS", LogMsgType.DEBUG);
            } 
            else
            {
                // Giveback collector default object.
                instanceSerPort.collector = mGeneralCollector;
                throw new Exception("连续加压测试 Fail");
            }

            bResult = pulseContinuousHandler.ResetDevice();
            if(!bResult)
            {
                // Giveback collector default object.
                instanceSerPort.collector = mGeneralCollector;
                throw new Exception("自动泄压 Fail");
            }

            // Giveback collector default object.
            instanceSerPort.collector = mGeneralCollector;

            return bResult;
        }

        private bool DoThreeBodyTest_Subsection()
        {
            string mmHgInfo;
            double bmmHgThreSValue = FileConfig.GetThresholdValue("mmHgThresholdValue");//加压mmHg门限值
            // 从配置文件中读取分段压力值
            if (!FileConfig.getmmHgListInfo("mmHg_pPressureList", out mmHgInfo))
            {
                this.ShowMsg(string.Format("{0} 脉压集合列表初始化失败", mmHgInfo), LogMsgType.ERROR);
                return false;
            }

            // 将分段压力值转换成int
            List<int> mmHgListInfo = mmHgInfo.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToList();
            
            // 创建三部基线压力
            Dictionary<BodyPart, double> baseLineMap = new Dictionary<BodyPart, double> 
            {
                {BodyPart.eBODY_PART_CUN, baseline_value[0]*100.0 },
                {BodyPart.eBODY_PART_GUAN, baseline_value[1]*100.0 },
                {BodyPart.eBODY_PART_CHI, baseline_value[2]*100.0 }
            };

            // 创建分段对象
            PulseThreeBodySubsection PSProcessing = new PulseThreeBodySubsection(baseLineMap, mmHgListInfo);
            instanceSerPort.collector = PSProcessing;
            PSProcessing.DeviceCommunication = mDCManager;
            PSProcessing.notifyMainForm += new PulseThreeBodySubsection.PulseContinuousNotifyDelegate<PulseCommonHelper.Display>(DisplayMessageToUI);
            PSProcessing.ThresholdRadio = bmmHgThreSValue;
            PSProcessing.RawDataPath = null;

            Log.Debug("FileConfig.CommonParam.AllowSavePulseData={0}", FileConfig.CommonParam.AllowSavePulseData);
            // Write pulse data to file.
            if (FileConfig.CommonParam.AllowSavePulseData > 0)
            {
                PSProcessing.UserRightHandSel = UserRightHandSel;
                PSProcessing.PhoneNumber = UserPhoneNum;
                PSProcessing.SerialNumber = mInputPCBSN;
                PSProcessing.RawDataPath = Application.StartupPath + "\\PulseData\\Segment";
            }

            bool ret = PSProcessing.DoSubsectionProcessing();
            if (ret)
            {
                RunFuncWithShowItem(true, "分段加压测试", "加压测试 PASS");
                this.ShowMsg("分段加压测试 PASS", LogMsgType.DEBUG);
            }
            else
            {
                throw new Exception("分段加压测试 Fail");
            }

            // 请求复位设备
            ret = PSProcessing.ResetDevice();
            if (!ret)
            {
                throw new Exception("自动泄压 Fail");
            }

            return ret;
        }

     #region ignore
            //手动测试
            private void btn_ManualTest_Click(object sender, EventArgs e)
        {
            this.ShowInfo("Running", Color.Yellow);
            scopeDY.Channels[0].Data.Clear();
            
            ProFrm Frm_ = null;
            this.Invoke(new EventHandler(delegate
            {
                Frm_ = new ProFrm(string.Format("请正确佩戴设备,并手动加压."));
                Frm_.ShowDialog(this);
                if (!Frm_.TestState)
                    this.ShowMsg(string.Format("未正确佩戴设备，测试结束"), LogMsgType.ERROR);
                else
                    this.btn_ManualPress.Enabled = true;
            }));
        }

        // 三部连续采脉
        private bool DoThreeBodyTest_Continuous()
        {
            PulseThreeBodyContinuous pulseContinuousHandler = new PulseThreeBodyContinuous();
            PulseThreeBodyContinuous.ContinuousResponseCode responseCode;
            bool bResult = false;
            uint loopCounter = 80;
            if (true)
            {
                string reason;

                pulseContinuousHandler.ResetContinuousConfigure();

                // must set collector to serialport
                instanceSerPort.collector = pulseContinuousHandler;

                Log.Debug("DoThreeBodyTest_Continuous");
                pulseContinuousHandler.notifyMainForm = new PulseThreeBodyContinuous.PulseContinuousNotifyDelegate<PulseCommonHelper.Display>(DisplayMessageToUI);
                pulseContinuousHandler.DeviceCommunication = mDCManager;

                // Write pulse data to file.
                if (FileConfig.CommonParam.AllowSavePulseData > 0)
                {
                    CreateTestLogFile(out LogFile_RecordmmHg);
                    Log.Debug("save filename: " + LogFile_RecordmmHg);
                    pulseContinuousHandler.RawDataFile = LogFile_RecordmmHg;
                }

                Log.Debug("DoThreeBodyTest_Continuous2");
                bResult = pulseContinuousHandler.ProcessContinuous();
            }

            if (bResult)
            {
                RunFuncWithShowItem(true, "连续加压测试", "加压测试 PASS");
                this.ShowMsg("连续加压测试 PASS", LogMsgType.DEBUG);
            }
            else
            {
                // Giveback collector default object.
                instanceSerPort.collector = mGeneralCollector;
                throw new Exception("连续加压测试 Fail");
            }

            bResult = pulseContinuousHandler.ResetDevice();
            if (!bResult)
            {
                // Giveback collector default object.
                instanceSerPort.collector = mGeneralCollector;
                throw new Exception("自动泄压 Fail");
            }

            // Giveback collector default object.
            instanceSerPort.collector = mGeneralCollector;

            return bResult;
        }

        /// <summary>
        /// 手动输入压力值,需要手动复位
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_ManualPress_Click(object sender, EventArgs e)
        {
            Thread nth = new Thread(() =>
            {
                this.Invoke(new EventHandler(delegate
                {
                    this.ShowInfo("Running", Color.Yellow);
                    this.btn_ManualPress.Enabled = false;
                    //refeshBaseLineData();
                }));

                int PressGasPumpValue_ = 0;

                //MaxMin_WaveData.Clear();

                GasPumpFrm Frm_ = null;
                this.Invoke(new EventHandler(delegate
                {
                    Frm_ = new GasPumpFrm(string.Format("请正确佩戴设备,状态指示灯正常."));
                    Frm_.ShowDialog(this);
                    if (Frm_.TestState)
                        PressGasPumpValue_ = Frm_.GetGasPumpValue;
                    Frm_.Dispose();
                }));

                if (!InitSerialPort())
                    throw new Exception(string.Format("串口打开失败"));

                if (!InitializePulseDevice())
                {
                    throw new Exception("Init MCU Info Fail");
                }

                // 开启脉压和气压采集
                byte[] temp;
                if (!mDCManager.SendCommandToDevice("SPStartPulsePressure", 0x64, out temp))
                    throw new Exception("开启脉压收集失败");
                if (!mDCManager.SendCommandToDevice("SPStartAirPressure", 0x95, out temp))
                    throw new Exception("开启气压收集失败");

                byte[] byteCmd_ = FileConfig.getSerialPortData("SPHeadmmHgData");
                List<byte> frameBytes = new List<byte>();
                byte[] byteData = BitConverter.GetBytes(PressGasPumpValue_ * 133);
                frameBytes.Add(byteData[1]);
                frameBytes.Add(byteData[0]);
                byte[] byteCmd = frameBytes.ToArray();//(byte[])alWriteData.ToArray(typeof(byte));
                byte[] final_byteCmd = new byte[byteCmd_.Length + byteCmd.Length];
                byteCmd_.CopyTo(final_byteCmd, 0);
                byteCmd.CopyTo(final_byteCmd, byteCmd_.Length);
                Log.Debug("SendCmd_mmHg :" + string.Format("{0}", string.Join(" ", final_byteCmd.Select(p => string.Format("{0:X2}", p)))));
                this.ShowMsg(string.Format("气泵手动加压 {0}mmHg,Waiting for {1}S...", PressGasPumpValue_, (10)), LogMsgType.DEBUG);
                byte[] payload;
                bool ret = mDCManager.SendCommandToDevice(final_byteCmd, "SPHeadmmHgData", 0x92, out payload);
                if (ret && payload[0] != 0x00)
                {
                    ret = false;
                    Log.Error("FormMain:" + "btn_ManualPress_Click() request the device failed to increase pressure");
                }

            });

            nth.Start();
        }

        //手动刷新脉压值显示
        private void btn_RefeshBaseLine_Click(object sender, EventArgs e)
        {
            this.ShowMsg("手动刷新脉压基线值", LogMsgType.INFO);
            refeshBaseLineData();
        }

        private double refeshBaseLineData()
        {
            do
            {
                this.Invoke((EventHandler)delegate
                {
                    if (string.IsNullOrWhiteSpace(this.textBox_curveValue.Text))
                    {
                        baseline_value[0] = 0;
                    }
                    else
                    {
                        baseline_value[0] = Convert.ToDouble(this.textBox_curveValue.Text);
                        textBox_baseline.Text = baseline_value.ToString();
                    }
                });
                Log.Debug("baseline_value :" + baseline_value[0]);
                if (baseline_value[0] > 0)
                    break;
            } while (true);

            return baseline_value[0];
        }
        //手动复位，气泵复位
        private void btn_StopReset_Click(object sender, EventArgs e)
        {
            Thread thread_ = new Thread(() => {
                this.Invoke(new EventHandler(delegate
                {
                    this.btn_ManualPress.Enabled = false;
                    this.btn_RefeshBaseLine.Enabled = false;
                    this.btn_ManualTest.Enabled = false;
                }));

                this.ShowMsg("手动复位...", LogMsgType.INFO);
                if(instanceSerPort == null)
                {
                    InitSerialPort();
                    InitializePulseDevice();
                }

                ResetDeviceStatus();
                ReleaseSerialPort();

                refeshBaseLineData();
                this.Invoke(new EventHandler(delegate
                {
                    this.btn_ManualPress.Enabled = true;
                    this.btn_RefeshBaseLine.Enabled = true;
                    this.btn_ManualTest.Enabled = true;
                }));
                this.ShowMsg("手动复位 PASS", LogMsgType.INFO);

            });

            thread_.Start();
        }
#endregion

        private void timerTotalTest(System.Timers.Timer t)
        {
            t.Elapsed += new System.Timers.ElapsedEventHandler(updateTestTotalTime);
            t.AutoReset = true;
            t.Enabled = true;
            t.Start();
        }

        private void timerDeTotalTest(System.Timers.Timer t)
        {
            t.Elapsed -= new System.Timers.ElapsedEventHandler(updateTestTotalTime);
            t.AutoReset = false;
            t.Enabled = false;
            t.Stop();
        }
        private void timerSensorSetting(System.Timers.Timer t)
        {
            t.Interval = 100;
            t.Elapsed += new System.Timers.ElapsedEventHandler(getGraphCurveValue);
            t.AutoReset = true;
            t.Enabled = true;
            t.Start();
        }

        private void timerSensorDesetting(System.Timers.Timer t)
        {
            if(t.Enabled)
            {
                t.Elapsed -= new System.Timers.ElapsedEventHandler(getGraphCurveValue);
                t.AutoReset = false;
                t.Enabled = false;
                t.Stop();
            }
        }
        private void updateTestTotalTime(Object myObject, EventArgs myEventArgs)
        {
            TimeCount++;
            TimeSpan temp = new TimeSpan(0, 0, (int)TimeCount);
            BeginInvoke(new Action(() =>
            {
                this.labTotalTime.Text = string.Format("{0}{1:00}:{2:00}:{3:00}", "测试时长 :",temp.Hours, temp.Minutes, temp.Seconds);
            }));
        }
        uint testTmp = 0;

        /// <summary>
        /// 实时显示当前脉压值和脉压差值
        /// 2020-6-24
        /// </summary>
        /// <param name="myObject"></param>
        /// <param name="myEventArgs"></param>
        private void getGraphCurveValue(Object myObject, EventArgs myEventArgs)
        {
            double airpresure_value = 0;
            double curveline_value = 0;
            double curDiffValue = 0;
            BeginInvoke(new Action(() =>
            {
                testTmp++;
                //this.ShowMsg("wave_data.Count :" + wave_data.Count,LogMsgType.INFO);
                bool check = mApplication.PluseData[BodyPart.eBODY_PART_CUN].Count == PulseApplicantion.QUEUE_PULSE_DATA_MAXIMUM ? true : false;
                if (check && FileConfig.PulseThreeBodyTest())
                {
                    
                    foreach(var item in mApplication.PluseData)
                    {
                        if(item.Key == BodyPart.eBODY_PART_CUN)
                        {
                            curveline_value = Math.Round(item.Value.Average(), 2);
                            curDiffValue = Math.Round((curveline_value - baseline_value[0]), 2);
                            //实时显示当前脉压值，1秒上报100次
                            this.textBox_curveValue.Text = curveline_value.ToString();
                            //实时显示脉压差值 单位: mbar
                            //this.textBox_pressed.Text = curDiffValue.ToString();

                            //实时显示脉压差值 单位: mmHg
                            curDiffValue = Math.Round(curDiffValue * 100 / 133.33, 2);
                            if (testTmp % 10 == 0)
                                this.textBox_pressed.Text = curDiffValue.ToString(); // mmHg
                        }
                        else if(item.Key == BodyPart.eBODY_PART_GUAN)
                        {
                            curveline_value = Math.Round(item.Value.Average(), 2);
                            curDiffValue = Math.Round((curveline_value - baseline_value[1]), 2);
                            //实时显示当前脉压值，1秒上报100次
                            this.textBox_curveValue1.Text = curveline_value.ToString();
                            //实时显示脉压差值 单位: mbar
                            //this.textBox_pressed1.Text = curDiffValue.ToString();

                            //实时显示脉压差值 单位: mmHg
                            curDiffValue = Math.Round(curDiffValue * 100 / 133.33, 2);
                            if (testTmp % 10 == 0)
                                this.textBox_pressed1.Text = curDiffValue.ToString(); // mmHg
                        }
                        else if(item.Key == BodyPart.eBODY_PART_CHI)
                        {
                            curveline_value = Math.Round(item.Value.Average(), 2);
                            curDiffValue = Math.Round((curveline_value - baseline_value[2]), 2);
                            //实时显示当前脉压值，1秒上报100次
                            this.textBox_curveValue2.Text = curveline_value.ToString();
                            //实时显示脉压差值 单位: mbar
                            //this.textBox_pressed2.Text = curDiffValue.ToString();

                            //实时显示脉压差值 单位: mmHg
                            curDiffValue = Math.Round(curDiffValue * 100 / 133.33, 2);
                            if (testTmp % 10 == 0)
                                this.textBox_pressed2.Text = curDiffValue.ToString(); // mmHg
                        }
                    }
                }
                else
                {
                    if(check && mApplication.PluseData.ContainsKey(BodyPart.eBODY_PART_CUN))
                    {
                        curveline_value = Math.Round(mApplication.PluseData[BodyPart.eBODY_PART_CUN].Average(), 2);
                        curDiffValue = Math.Round((curveline_value - baseline_value[0]), 2);
                        //实时显示当前脉压值，1秒上报100次
                        this.textBox_curveValue.Text = curveline_value.ToString();
                        //实时显示脉压差值 单位: mbar
                        //this.textBox_pressed.Text = curDiffValue.ToString();

                        //实时显示脉压差值 单位: mmHg
                        curDiffValue = Math.Round(curDiffValue * 100 / 133.33, 2);
                        if (testTmp % 10 == 0)
                            this.textBox_pressed.Text = curDiffValue.ToString(); // mmHg
                    }
                }

                if (airPressure_data.Count == QUEUE_AIRPRESSURE_LENGTH)
                {
                    airpresure_value = Math.Round(airPressure_data.Average(), 2);

                    //this.textBox_airPressure.Text = airpresure_value.ToString();//实时显示当前气压值，1秒上报10次

                    //testTmp++;
                    // airpresure_value = Math.Round(airpresure_value / 133.33, 2);
                    if (testTmp % 10 == 0)
                        this.textBox_airPressure.Text = airpresure_value.ToString(); // Pa
                }
            }));
        }


        private bool WriteSerialNumber(string serialNum)
        {
            int offset = 0;
            if (serialNum.Length > 16 + offset)
            {
                MessageBox.Show("SN号长度错误！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            if (serialNum.Length != 16 + offset)
            {
                MessageBox.Show("SN号长度错误！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            string sn_from_scanner = serialNum.Substring(offset, 16);
            // 检查长度是不是16位，防错
            if (sn_from_scanner.Length != 16)
            {
                MessageBox.Show("SN号长度为16位!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            // 获取相应信息的字符串 GMMX002 2210 2 0001
            string year_str = sn_from_scanner.Substring(7, 2);
            string month_str = sn_from_scanner.Substring(9, 2);
            string prodStatus_str = sn_from_scanner.Substring(11, 1);
            string number_str = sn_from_scanner.Substring(12, 4);
            // 将字符串转化为16进制的数值, 取高八位写入地址
            //out.write((message.length>>8)&0xff);//
            //取低八位写入高地址中
            //out.write(message.length&0xff);
            //取低八位写入高地址中
            int year = Convert.ToInt32(year_str) & 0xFF;
            int month = Convert.ToInt32(month_str) & 0x0F;
            int prodStatus = Convert.ToInt32(prodStatus_str) & 0x0F;
            int number = Convert.ToInt32(number_str) & 0xFFFF;
            this.ShowMsg("number & 0xFF :" + (number & 0xFF) + ",number >> 8 & 0xFF :" + (number >> 8 & 0xFF),LogMsgType.INFO);
            byte[] byteCmd = {Convert.ToByte(number & 0xFF), Convert.ToByte(number >> 8 & 0xFF),
                    Convert.ToByte(month << 4 | prodStatus), Convert.ToByte(year) };
            byte[] byteCmd_ = FileConfig.getSerialPortData("SPWritePcbSN");
            byte[] Cmdata_set_sn = new byte[byteCmd.Length+byteCmd_.Length];
            byteCmd_.CopyTo(Cmdata_set_sn, 0);
            byteCmd.CopyTo(Cmdata_set_sn, byteCmd_.Length);

            // Cmdata分别表示为帧头（4个字节），长度，指令，年份，月份(高四位)|序号高4位，序号9-16位，序号低8位
            //byte[] Cmdata_set_sn = { 0x55, 0x55, 0xaa, 0xaa, 0x05, 0xc2, Convert.ToByte(number & 0xFF), Convert.ToByte(number >> 8 & 0xFF),
            //Convert.ToByte(month << 4 | number >> 16), Convert.ToByte(year) };

            this.ShowMsg("Write SN(0:X2) :" + ConvertFuncs.ByteArrayToHexString(Cmdata_set_sn), LogMsgType.INFO);
            
            byte[] payload;
            return mDCManager.SendCommandToDevice(Cmdata_set_sn, "SPWritePcbSN", 0xC4, out payload);            
        }

        private void ShowInfo(string info, Color clr)
        {
            this.lbEndMsg.Invoke(new EventHandler(delegate
            {
                this.lbEndMsg.ForeColor = clr;
                this.lbEndMsg.Text = info;
            }));
        }

        private void ShowMsg(string msg, LogMsgType msgType)
        {
            Color _color = (msgType == LogMsgType.ERROR ? Color.Red : msgType == LogMsgType.DEBUG ? Color.Blue : Color.Black);
            if (msgType != LogMsgType.MSG)
                Log.Debug(msg);
            if (rtbMsg.InvokeRequired)
            {
                Action<string> act = (obj) =>
                {
                    rtbMsg.SelectionColor = _color;
                    rtbMsg.AppendText(obj + "\r\n");
                    rtbMsg.ScrollToCaret();
                };
                rtbMsg.Invoke(act, msg);
            }
            else
            {
                rtbMsg.SelectionColor = _color;
                rtbMsg.AppendText(msg + "\r\n");
                rtbMsg.ScrollToCaret();
            }
        }
        public bool RunFuncWithShowItem(bool FuncResult, string itemName, string Iteminfo = "")
        {
            bool bok = FuncResult;
            showItem(itemName, Iteminfo, 1, bok ? 1 : 0, 1);

            return bok;
        }
        public void showItem(string ItemName, string ItemInfo, double dlow, double value, double dhigh, string unit = "")
        {
            UIItemInfo info = new UIItemInfo();
            info.ItemName = ItemName.Trim();
            info.info = ItemInfo.Trim();
            //info.LimitLow = dlow.ToString();
            info.TestValue = value.ToString();
            //info.LimitHigh = dhigh.ToString();
            //info.TestUnit = unit;
            info.ItemResult = (dlow <= value && value <= dhigh) ? "PASS" : "FAIL";

            AppEvent.CallEvent(this, new AppEventArgs(EventId.AddLog, 999, EventState.LOG_ITEM, info, null));
        }


        /// <summary>
        /// 对于指定类中自定义事件，移除其中的委托链的全部订阅方法，
        /// 或者移除委托链中的指定方法名的订阅。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="c"></param>
        /// <param name="event_name"></param>
        /// <param name="methodname"></param>
        public static void RemoveEvent<T>(T c, string event_name, string methodname = "")
        {
            Delegate[] invokeList = GetObjectEventList_V2(c, event_name);
            if (invokeList == null) 
                return;

            foreach (Delegate dlgateItme in invokeList)
            {
                Log.Debug("Event.Method.Name: " + dlgateItme.Method.Name);
                if (methodname != "" && dlgateItme.Method.Name != methodname)
                    continue;
                typeof(T).GetEvent(event_name).RemoveEventHandler(c, dlgateItme);
                Log.Debug("Remove an event of " + event_name);
            }
        }
        public static Delegate[] GetObjectEventList_V2(object p_object, string p_EventName)
        {
            FieldInfo _fieldInfo;
            Delegate _ObjDele;
            object _FieldValue;

            _fieldInfo = p_object.GetType().GetField(p_EventName,
                    BindingFlags.Instance |
                    BindingFlags.NonPublic |
                    BindingFlags.Static |
                    BindingFlags.Public);
            if (_fieldInfo == null)
                return null;
            _FieldValue = _fieldInfo.GetValue(p_object);

            if (_FieldValue == null || !(_FieldValue is Delegate))
                return null;
            _ObjDele = (Delegate)_FieldValue;

            return _ObjDele.GetInvocationList();
        }

       


        private void toolStripButtonReplay_Click(object sender, EventArgs e)
        {
            //openFileDialogWave = new OpenFileDialog();
            //if (openFileDialogWave.ShowDialog() == DialogResult.OK)
            //{
            //    OpenWaveName = openFileDialogWave.FileName;
            //    //MessageBox.Show(OpenWaveName);
            //    string readstr = File.ReadAllText(OpenWaveName);
            //    byte[] ReplayData = ConvertFuncs.HexStringToByteArray(readstr);
            //    scopeDY.Channels[0].Data.Clear();
            //    scopeDY.SizeLimit = 0;
            //    BeginInvoke(new Action(() => {
            //        for (int i = 0; i < (ReplayData.Length) / 7; i++)
            //        {
            //            scopeDY.Channels[0].Data.AddYPoint((ReplayData[5 + i * 7]) | (ReplayData[6 + i * 7] << 8));
            //        }
            //    }));

            //}
        }

        private void tsBtn_version_Click(object sender, EventArgs e)
        {
            MessageBox.Show(Application.ProductName + "-" + Application.ProductVersion, "版本信息", MessageBoxButtons.OK);
        }

        /// <summary>
        /// 写入log函数，在文件f中写入一行
        private void LogWriter(string logfile, string message)
        {
            System.IO.StreamWriter sw = new StreamWriter(logfile, true);
            try
            {
                sw.Write(System.String.Format("{0} ", message));
            }
            finally
            {
                sw.Close();
            }
        }

        private void CreateTestLogFile(out string logFileName)
        {
            logFileName = "";
            string file_path = Application.StartupPath + "\\PulseData";
            string strdate = DateTime.Now.ToString("yyyyMMdd");  
            string str_hms = DateTime.Now.TimeOfDay.ToString("hhmmssfff");
            logFileName = file_path + "\\" + String.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}-{7}.dat",
                "GMMX", UserPhoneNum, "3", mInputPCBSN.Substring(4),
                strdate, str_hms,
                baseline_value[0] > 0 ? baseline_value[0]*100 : 0 ,
                UserRightHandSel ? "R" : "L");            
        }

        private void toolStripButtonExit_Click(object sender, EventArgs e)
        {
            this.ShowMsg("Exit_Click", LogMsgType.INFO);
            this.Close();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.ShowMsg("MainForm_FormClosing Click", LogMsgType.INFO);
            if (MessageBox.Show("Exit?", Application.ProductName, MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                try
                {
                    toolStripButtonStopScope_Click(null, null);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("Close MainForm...Delete packet And Kill Process Fail...{0}", ex.Message));
                }
                Dispose();
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void toolStripButtonOpenLog_Click(object sender, EventArgs e)
        {
            Process.Start("explorer.exe", Application.StartupPath + "\\logs");
        }

        private string pathname = string.Empty; //定义路径名变量

        private void toolStripButtonReplay_Click_1(object sender, EventArgs e)
        {
            //readLine();
            //return;
            OpenFileDialog file = new OpenFileDialog();
            file.InitialDirectory = Application.StartupPath + "\\PulseData\\";
            file.Filter = "所有文件(*.dat)|*.*";
            file.ShowDialog();
            pathname = file.FileName;//获得文件的绝对路径
            if (file.FileName != string.Empty)
            {
                ArrayList alReceiveData = new ArrayList();
                FileStream fs = new FileStream(file.FileName, FileMode.Open, FileAccess.ReadWrite);
                StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8);
                scopeDY.Channels[0].Data.Clear();
                scopeDY.SizeLimit = 0;
                //scopeDY.Height = 334;
                //scopeDY.Width = 1159;
                if (!File.Exists(pathname))
                    return;
                string sLine = sr.ReadLine();
                foreach (string i in sLine.Split(' '))
                {
                    if (!string.IsNullOrWhiteSpace(i))
                        alReceiveData.Add(Convert.ToByte(i, 16));
                }
                Log.Debug("alReceiveData.Count :" + alReceiveData.Count, LogMsgType.DEBUG);

                while (true)
                {
                    byte[] receivePulseData = (byte[])alReceiveData.GetRange(0, 11).ToArray(typeof(byte));
                    BeginInvoke(new Action(() =>
                    {
                        int d = (receivePulseData[7]) | (receivePulseData[6] << 8) | (receivePulseData[5] << 16);
                        double pPData = d / 100.0 / 32;
                        pPData = Math.Round(pPData, 2);
                        scopeDY.Channels[0].Data.AddYPoint(pPData);
                    }));
                    alReceiveData.RemoveRange(0, 11);
                    if (alReceiveData.Count < 11)
                        break;
                }
                sr.Close();
                fs.Close();

                BeginInvoke(new Action(() =>
                {
                    this.scopeDY.RefreshView();
                    MatlabSaveToBitmap();
                }));
            }
        }
     
        private void toolStripButtonAnalyse_Click(object sender, EventArgs e)
        {
            //定时任务，开始采集数据
            //analyer_timer.Enabled = true;
            //analyer_timer.Elapsed += new System.Timers.ElapsedEventHandler(AnalyseProcess);
            //analyer_timer.Start();

            ////显示进度条
            ////panelProcess.Visible = true;
            //progress_thread = new System.Threading.Thread(new System.Threading.ThreadStart(TheadProcess));
            //progress_thread.Start();
        }
        

        private void SaveLog()
        {
#region SAVE_LOG
            try
            {
                if (FileConfig.CommonParam.UploadLogEnable)
                {
                    var logdir = AppDomain.CurrentDomain.BaseDirectory + "Logs";
                    var logDirBack = AppDomain.CurrentDomain.BaseDirectory + "LogsBack\\";
                    string zipfilename = "";

                    if (Directory.Exists(logdir))
                    {
                        CopyDirectory(logdir, logDirBack, false);
                        zipfilename = string.Format("{2}{0}_{1}.zip"
                         , mInputPCBSN
                         , DateTime.Now.ToString("yyMMddHHmmss")
                         , logDirBack);//logDirBack 
                        string[] args = new string[] { logDirBack, zipfilename };
                        if(ZipHelper.Instance.ZipFileMain(args, null) > 0)
                        {
                            string[] files = Directory.GetFiles(logDirBack, "*.txt");
                            foreach (var file in files)
                            {
                                File.Delete(file);
                            }
                        }
                        //ZipHelper.Instance.Zip(file, zipfilename);
                        //var files = Directory.GetFiles(logDirBack);
                        //if (files != null && files.Length > 0)
                        //{
                        //    foreach (var file in files)
                        //    {
                        //        ZipHelper.Instance.Zip(file, zipfilename);
                        //    }
                        //    //ZipHelper.Instance.Zip(logDirBack, zipfilename);
                        //}
                        if (File.Exists(zipfilename))
                        {
                            FtpClient ftp = new FtpClient(FileConfig.CommonParam.UploadIpaddress
                                    , FileConfig.CommonParam.UploadUser
                                    , FileConfig.CommonParam.UploadPwd
                                    , FileConfig.CommonParam.uploaderRemoteFolder);
                            ftp.Connect();
                            //if (!string.IsNullOrWhiteSpace(wonumber))
                            //{
                            //    var dirlist = ftp.GetCurDirList(FtpFileType.Directory);
                            //    if (dirlist == null || dirlist.Count < 1 || !dirlist.Exists(p => p.FileName == wonumber))
                            //        ftp.MkDir(wonumber);
                            //    ftp.ChildDir(wonumber);
                            //}

                            ftp.Upload(zipfilename);
                            ftp.DisConnect();

                            try
                            {
                                File.Delete(zipfilename);
                            }
                            catch (Exception ex)
                            {
                                Log.Debug("delete ziplogfile error:" + ex.Message);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.ShowMsg("Save ftp log FAIL:" + ex.Message, LogMsgType.ERROR);
            }
#endregion
        }

        private bool CopyDirectory(string SourcePath, string DestinationPath, bool overWriteExisting)
        {
            bool ret = false;
            try
            {
                SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\";
                DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\";

                if (Directory.Exists(DestinationPath))
                    Directory.Delete(DestinationPath, true);

                if (Directory.Exists(SourcePath))
                {
                    if (Directory.Exists(DestinationPath) == false)
                        Directory.CreateDirectory(DestinationPath);

                    foreach (string file in Directory.GetFiles(SourcePath))
                    {
                        FileInfo flinfo = new FileInfo(file);
                        flinfo.CopyTo(DestinationPath + flinfo.Name, overWriteExisting);
                    }
                    foreach (string dir in Directory.GetDirectories(SourcePath))
                    {
                        DirectoryInfo drinfo = new DirectoryInfo(dir);
                        if (CopyDirectory(dir, DestinationPath + drinfo.Name, overWriteExisting) == false)
                            ret = false;
                    }
                }
                ret = true;
            }
            catch (Exception ex)
            {
                ret = false;
                this.ShowMsg("Copy Log Error:" + ex.Message, LogMsgType.INFO);
            }
            return ret;
        }
    }

    public enum TestItemFlow
    {
        NA,
        Led1Test,
        SFTAirTest,
    }

}

#if FALSE
if (FileConfig.PulseSFTTest())
{
    byte[] byteCmd_ = FileConfig.getSerialPortData("SPHeadmmHgData");
    List<byte> frameBytes = new List<byte>();
    byte[] byteData = BitConverter.GetBytes(165 * 133);//强制加压165mmHg
    frameBytes.Add(byteData[1]);
    frameBytes.Add(byteData[0]);
    byte[] byteCmd = frameBytes.ToArray();
    byte[] final_byteCmd = new byte[byteCmd_.Length + byteCmd.Length];
    byteCmd_.CopyTo(final_byteCmd, 0);
    byteCmd.CopyTo(final_byteCmd, byteCmd_.Length);
    Log.Debug("SendCmd_mmHg :" + string.Format("{0}", string.Join(" ", final_byteCmd.Select(p => string.Format("{0:X2}", p)))));
    instanceSerPort.SendData(final_byteCmd, 0, final_byteCmd.Length);
    if (this.InvokeRequired)
    {
        this.Invoke(new EventHandler(delegate
        {
            LedFrm ledFrm = new LedFrm(instanceSerPort, TestItemFlow.SFTAirTest);
            ledFrm.ShowDialog();
            finalResult = ledFrm.TestState;
            RunFuncWithShowItem(finalResult, "气囊充气测试", "气囊充气测试结果");
            if (finalResult)
            {
                this.ShowMsg("气囊充气测试通过", LogMsgType.INFO);
                WaitTestEndEvent.Set();
            }
            else
            {
                throw new Exception("气囊充气测试失败");
            }
        }));
    }
    else
    {
        LedFrm ledFrm = new LedFrm(instanceSerPort, TestItemFlow.SFTAirTest);
        ledFrm.ShowDialog();
        finalResult = ledFrm.TestState;
        if (finalResult)
        {
            this.ShowMsg("气囊充气测试通过", LogMsgType.INFO);
            WaitTestEndEvent.Set();
        }
        else
        {
            throw new Exception("气囊充气测试 FAIL");
        }
    }
    this.ShowMsg("SPResetData", LogMsgType.INFO);
    SendResetCmd("SPHeadmmHgData", "SPResetData");
    WaitTestEndEvent.WaitOne();

    RunFuncWithShowItem(finalResult, "单板功能测试", "单板功能测试通过");
}
#endif
